<?php
/**
 * DMFramework
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @url http://dmframework.nl
 */

/**
 * The file library
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @package System.Library
 */
class Dmf_File
{
       /**
     * The full filename
     * 
     * @var string 
     */
    private $_filename;
    
    /**
     * Pathinfo -> Basename
     *  
     * @var string 
     */
    public $basename;
    
    /**
     * Pathinfo -> Dirname
     * 
     * @var string 
     */
    public $dirname;
    
    /**
     * Pathinfo -> Filename
     * 
     * @var string 
     */
    public $filename;
    
    /**
     * Pathinfo -> Extension
     * 
     * @var string 
     */
    public $extension;
    
    /**
     * File rights (in octal)
     * 
     * @var float 
     */
    public $rights;
    
    /**
     * Constructor
     * 
     * @param string $filename 
     */
    public function __construct( $filename )
    {
        if ( @filetype( $filename ) != 'file' && file_exists( $filename ) )
        {
            throw new Exception( 'Path: "' . $filename . '" is not a file.' );
        }
         
        $this->_filename = realpath( $filename );
        
        if ( ! file_exists( $filename ) )
        {
            $fh = fopen( $filename, 'w+' );
            fclose( $fh );
            
            if ( ! $fh )
            {
                throw new Exception( 'Could not create file: "' . $filename . '".' );
            }
            
            return $this->__construct( $filename );
        }
        
        $pathinfo = pathinfo( $this->_filename );
        
        $this->basename  = $pathinfo['basename'];
        $this->dirname   = isset( $pathinfo['dirname'] ) ? $pathinfo['dirname'] : null;
        $this->filename  = $pathinfo['filename'];
        $this->filepath = $this->_filename;
        $this->filesize = filesize( $this->_filename );
        
        if ( isset( $pathinfo['extension'] ) )
        {
            $this->extension = $pathinfo['extension'];
        }
        
        $this->rights = substr( sprintf( '%o', fileperms( $this->_filename ) ), -4 );
    }
    
   /**
     * Chmod a directory (not recursive).
     * 
     * @param float $rights
     * @return boolean 
     */
    public function chmod( $rights )
    {
        if ( $rights === false )
        {
            return true;
        }
        
        $rights = ( substr( $rights, 0, 1 ) == '0' || substr( $rights, 0, 1 ) == '1' ) ? $rights : '0' . $rights;
        
        if ( @chmod( $this->_filename, octdec( $rights ) ) )
        {
            $this->__construct( $this->_filename );
            
            return true;
        }
        else
        {
            return false;
        }
    }
    
    /**
     * Rename a Directory
     * 
     * @param string $newname
     * @return boolean 
     */
    public function rename( $newname )
    {
        if ( rename( $this->_filename, $this->dirname . '/' . $newname ) )
        {
            $this->__construct( $this->dirname . '/' . $newname );
            
            return true;
        }
        else
        {
            return false;
        }
    }
    
    /**
     * Write content to a file
     * 
     * @param string $content
     * @param boolean $append
     * @return boolean 
     */
    public function write( $content, $append = false )
    {
        if ( $append === true )
        {
            return file_put_contents( $this->_filename, $content, FILE_APPEND | LOCK_EX );
        }
        else
        {
            return file_put_contents( $this->_filename, $content, LOCK_EX );
        }
    }
    
    /**
     * Simply delete a file
     * 
     * @return boolean 
     */
    public function delete()
    {
        return unlink( $this->_filename );
    }
    
    /**
     * Copy file to destination
     * 
     * @param string $dest 
     * @return boolean
     */
    public function copy( $dest )
    {
        if ( is_dir( $dest ) )
        {
            $dest = $dest . '/' . $this->basename;
        }
        
        if ( @copy( $this->_filename, $dest ) )
        {
            $this->__construct( $dest );
            
            return true;
        }
        else
        {
            return false;
        }
    }
    
    /**
     * Move a file
     * 
     * @param string $dest
     * @return boolean 
     */
    public function move( $dest )
    {
        if ( is_dir( $dest ) )
        {
            $dest = $dest . '/' . $this->basename;
        }
        
        $oldFilepath = $this->_filename;
        
        if ( $this->copy( $dest ) && @unlink( $oldFilepath ) )
        {
            $this->__construct( $dest );
            
            return true;
        }
        else
        {
            return false;
        }
    }
    
    /**
     * Get json-parsed content
     * 
     * @return array 
     */
    public function getJson( $asArray = true )
    {
        return json_decode( file_get_contents( $this->_filename ), $asArray );
    }
    
    /**
     * Get unserialized content
     * 
     * @return mixed 
     */
    public function getPhp()
    {
        return unserialize( file_get_contents( $this->_filename ) );
    }
    
    /**
     * Returnes an array with difference lines
     * 
     * @param string $otherFile
     * @param boolean $reverse
     * @return array 
     */
    public function diff( $otherFile, $reverse = false )
    {
        $this_file_array  = explode( "\n", file_get_contents( $this->_filename ) );
        $this_other_array = explode( "\n", file_get_contents( $otherFile ) );
        
        if ( $reverse !== false )
        {
            return array_diff_assoc( $this_file_array, $this_other_array );
        }
        else
        {
             return array_diff_assoc( $this_other_array, $this_file_array );
        }
    }
    
    /**
     * Get xml object with content
     * 
     * @return SimpleXMLElement 
     */
    public function getXml()
    {
        return new SimpleXMLElement( file_get_contents( $this->_filename ) );
    }
    
    /**
     * Get body as string
     * 
     * @return string 
     */
    public function getContent()
    {
        return file_get_contents( $this->_filename );
    }
}